Jerry's Log

Statement vs PreparedStatement

contents

다음은 StatementPreparedStatement에 대한 비교입니다.

이 용어들은 주로 Java (JDBC) 서 사용되지만, SQL 데이터베이스와 상호 작용하는 거의 모든 프로그래밍 언어(PHP, Python, C# 등)에 동일하게 적용되는 개념입니다.


1. 핵심 정의

Statement

PreparedStatement


2. 실행 아키텍처 (내부 구조)

차이점을 이해하려면, 데이터베이스 엔진이 쿼리를 받았을 때 수행하는 4단계 과정을 알아야 합니다.

  1. 파싱(Parsing): 문법(철자, 구문) 확인.
  2. 컴파일(Compiling): 기계가 이해할 수 있는 코드로 변환.
  3. 최적화(Optimization): 실행 계획(인덱스 사용 여부 등) 수립.
  4. 실행(Execution): 쿼리 실행 및 데이터 인출.

"Statement"의 처리 방식:

"PreparedStatement"의 처리 방식:


3. 가장 큰 차이점: 보안 (SQL Injection)

이것이 가장 중요한 차이점입니다.

"Statement"의 취약점

문자열 결합(String Concatenation) 을 사용합니다.

// 나쁜 예
String username = "hacker' OR '1'='1";
String sql = "SELECT * FROM Users WHERE name = '" + username + "'";

"PreparedStatement"의 방어

플레이스홀더(Placeholder, ?) 를 사용합니다.

// 좋은 예
String sql = "SELECT * FROM Users WHERE name = ?";
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setString(1, "hacker' OR '1'='1");

4. 상세 비교표

특징 Statement PreparedStatement
파라미터 입력 문자열에 직접 결합 (Concatenation). 실행 시점에 플레이스홀더(?)로 전달.
컴파일 매번 새로 컴파일함. 한 번 컴파일하고 재사용함 (Pre-compiled).
성능 반복 쿼리 시 느림. 반복 쿼리 시 빠름 (캐시 히트).
보안 🛑 SQL Injection에 취약함. ✅ SQL Injection에 안전함.
통신 프로토콜 텍스트 프로토콜 사용 (부피가 큼). 주로 바이너리 프로토콜 사용 (컴팩트함).
가독성 지저분함 (따옴표 처리가 복잡). 깔끔함 (로직이 명확히 보임).
사용처 DDL (CREATE, ALTER). DML (SELECT, INSERT, UPDATE).

5. 언제 Statement를 써야 할까요?

"PreparedStatement가 무조건 좋으니까 이것만 써야지"라고 생각할 수 있습니다. 99%는 맞습니다.

하지만 딱 하나의 예외가 있는데, 바로 DDL (데이터 정의 언어) 입니다.

이런 쿼리들은 프로그램 수명 주기 동안 한 번만 실행되며, 사용자 입력 파라미터를 받지 않고, 캐싱을 통한 성능 이점도 없기 때문에 일반 Statement를 사용해도 무방합니다.

references